home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / strategy / vga_card.000 / vga_cardgames-1.3.1.tar / vga_cardgames / klondike.c < prev    next >
C/C++ Source or Header  |  1994-05-05  |  7KB  |  389 lines

  1. /*
  2.  * Klondike
  3.  *
  4.  * Copyright (C) Evan Harris, 1991, 1994
  5.  *
  6.  * Permission is granted to freely redistribute and modify this code,
  7.  * providing the author(s) get credit for having written it.
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <getopt.h>
  12.  
  13. #include "klondike.h"
  14.  
  15. unsigned char    column[COLUMNS];        /* First card of column */
  16. unsigned char    stock, pile;            /* First card of stock, pile */
  17. short        cards[NUMCARDS];        /* Positions of cards */
  18. unsigned char    next[NUMCARDS];            /* Card underneath */
  19. unsigned char    hidden[NUMCARDS];        /* Cards which are face down */
  20. unsigned char    foundation[NUMSUITS];
  21.  
  22. int stockcycled;        /* The number of times stock has been cycled */
  23.  
  24.  
  25. void main(int argc, char **argv)
  26. {
  27.     short cmd, dest;
  28.     int cycle = 0, stockmove = 1;
  29.     int c, err = 0;
  30.  
  31.     while ((c = getopt(argc, argv, "cm:")) != -1) {
  32.     switch (c) {
  33.       case 'c':
  34.         cycle = 1;
  35.         break;
  36.       case 'm':
  37.         stockmove = atoi(optarg);
  38.         if (stockmove == 0) {
  39.         err++;
  40.         }
  41.         break;
  42.       case '?':
  43.         err++;
  44.         break;
  45.     }
  46.     }
  47.     if (err) {
  48.     fprintf(stderr, "Usage: %s [-c] [-m N]", argv[0]);
  49.     fprintf(stderr, "\t-c    cycle through stock forever\n");
  50.     fprintf(stderr, "\t-m N  move through stock N cards at a time\n");
  51.     exit(1);
  52.     }
  53.  
  54.  
  55.     
  56.     InitDisplay(argc, argv);
  57.  
  58.     InitRandom(NEW);
  59.     Deal();
  60.  
  61.     for (;;) {
  62.     cmd = GetCmd();
  63.     if (cmd == QUIT) {
  64.         EndDisplay();
  65.         exit(0);
  66.     }
  67.     else if (cmd == NEWGAME) {
  68.         InitRandom(NEW);
  69.         Deal();
  70.     }
  71.     else if (cmd == RESTART) {
  72.         InitRandom(LAST);
  73.         Deal();
  74.     }
  75.     else if (cmd == FROMSTOCK) {
  76.         FromStock(cycle, stockmove);
  77.     }
  78.     else if (ISCARD(NOHINT(cmd))) {
  79.         dest = FindDest(cmd);
  80.         if (dest != NOPOSN)
  81.         MakeMove((unsigned char)NOHINT(cmd), dest);
  82.     }
  83.     }
  84.  
  85.     /* Never reached */
  86. }
  87.  
  88.  
  89. void Deal()
  90. {
  91.     unsigned char i, j;
  92.     unsigned char row, col;
  93.     short r;
  94.  
  95.     /* Initialise the deck */
  96.     for (i = 0; i < NUMCARDS; i++) {
  97.     cards[i] = NOPOSN;
  98.     next[i] = NOCARD;
  99.     }
  100.     for (i = 0; i < NUMSUITS; i++)
  101.     foundation[i] = ACE;
  102.     pile = NOCARD;
  103.         
  104.     /* Deal the deck */
  105.     row = 0;
  106.     col = 0;
  107.     for (i = 0; i < NUMCARDS; i++) {
  108.     r = Random(NUMCARDS - i);
  109.     for (j = 0; j < NUMCARDS && r >= 0; j++) {
  110.         if (cards[j] == NOPOSN)
  111.         r--;
  112.     }
  113.     r = j - 1;
  114.  
  115.     cards[r] = POSN(col, row);
  116.     if (col != STOCK) {
  117.         if (row == 0)
  118.         column[col] = r;
  119.         else {
  120.         for (j = 0; cards[j] != POSN(col, row - 1); j++)
  121.             ;
  122.         next[j] = r;
  123.         }
  124.         if (col == row) {
  125.         hidden[r] = 0;
  126.         col++; 
  127.         row = 0;
  128.         }
  129.         else {
  130.         hidden[r] = 1;
  131.         row++;
  132.         }
  133.     }
  134.     else {
  135.         if (row == 0)
  136.         stock = r;
  137.         else {
  138.         for (j = 0; cards[j] != POSN(col, row - 1); j++)
  139.             ;
  140.         next[j] = r;
  141.         }
  142.         hidden[r] = 0;
  143.         row++;
  144.     }
  145.     }
  146.  
  147.     stockcycled = 0;
  148.  
  149.     for (i = 0; i < COLUMNS; i++)
  150.     DisplayColumn((short)i);
  151.     DisplayFoundations();
  152.     DisplayStockPile();
  153.  
  154.     return;
  155. }
  156.  
  157.  
  158. short FindDest(short card)
  159. {
  160.     unsigned char i, c;
  161.     short move;
  162.  
  163.     if (HASHINT(card))
  164.     return FindHintedDest((short)NOHINT(card), (short)HINT(card));
  165.  
  166.     move = CanMoveOff((unsigned char)card);
  167.     if (move == DESIRABLE)
  168.     return MOVEOFF;
  169.  
  170.     if (TYPE(card) == KING) {
  171.     if (ROW(cards[card]) == 0 && COL(cards[card]) != PILE) {
  172.         if (move == POSSIBLE)
  173.         return MOVEOFF;
  174.         else
  175.         return NOPOSN;
  176.     }
  177.     for (i = 0; i < COLUMNS; i++)
  178.         if (column[i] == NOCARD)
  179.         return (short)POSN(i, 0);
  180.     }
  181.     else {
  182.     for (i = 0; i < COLUMNS; i++)
  183.         if (i != COL(cards[card]) && column[i] != NOCARD) {
  184.         c = column[i];
  185.         while (next[c] != NOCARD)
  186.             c = next[c];
  187.         if ((TYPE(c) == TYPE(card) + 1) &&
  188.             ((ISBLACK(c) && ISRED(card)) || 
  189.              (ISRED(c) && ISBLACK(card)))) {
  190.             return (short)POSN(COL(cards[c]), ROW(cards[c]) + 1);
  191.         }
  192.         }
  193.     }
  194.  
  195.     if (move == POSSIBLE)
  196.     return MOVEOFF;
  197.     else
  198.     return NOPOSN;
  199. }
  200.  
  201.  
  202. short FindHintedDest(short card, short hint)
  203. {
  204.     unsigned char c;
  205.     short move;
  206.  
  207.     if (hint == FOUNDATION) {
  208.     move = CanMoveOff((unsigned char)card);
  209.     if (move != IMPOSSIBLE)
  210.         return MOVEOFF;
  211.     else
  212.         return NOPOSN;
  213.     }
  214.  
  215.     if (TYPE(card) == KING) {
  216.     if (ROW(cards[card]) == 0 && COL(cards[card]) != PILE)
  217.         return NOPOSN;
  218.     if (column[hint] == NOCARD)
  219.         return (short)POSN(hint, 0);
  220.     }
  221.     else {
  222.     if (hint != COL(cards[card])) {
  223.         c = column[hint];
  224.         while (next[c] != NOCARD)
  225.         c = next[c];
  226.         if ((TYPE(c) == TYPE(card) + 1) &&
  227.         ((ISBLACK(c) && ISRED(card)) || 
  228.          (ISRED(c) && ISBLACK(card))))
  229.         return (short)POSN(COL(cards[c]), ROW(cards[c]) + 1);
  230.     }
  231.     }
  232.  
  233.     return NOPOSN;
  234. }
  235.  
  236.  
  237. void MakeMove(unsigned char card, short dest)
  238. {
  239.     short col, row, oldcol;
  240.     unsigned char c, i;
  241.  
  242.     if (dest == MOVEOFF) {
  243.     MoveOff(card);
  244.     return;
  245.     }
  246.  
  247.     col = COL(dest);
  248.     row = ROW(dest);
  249.     oldcol = -1;
  250.  
  251.     if (pile == card) {
  252.     pile = next[card];
  253.     next[card] = NOCARD;
  254.     oldcol = PILE;
  255.     }
  256.     for (i = 0; oldcol == -1 && i < COLUMNS; i++) {
  257.     if (column[i] == card) {
  258.         column[i] = NOCARD;
  259.         oldcol = i;
  260.     }
  261.     }
  262.     for (i = 0; oldcol == -1 && i < NUMCARDS; i++) {
  263.     if (next[i] == card) {
  264.         if (hidden[i])
  265.         hidden[i] = 0;
  266.         next[i] = NOCARD;
  267.         oldcol = COL(cards[i]);
  268.     }
  269.     }
  270.  
  271.     if (row > 0) {
  272.     c = column[col];
  273.     while (next[c] != NOCARD)
  274.         c = next[c];
  275.     next[c] = card;
  276.     }
  277.     else
  278.     column[col] = card;
  279.     while (card != NOCARD) {
  280.     cards[card] = POSN(col, row++);
  281.     card = next[card];
  282.     }
  283.  
  284.     DisplayColumn(oldcol);
  285.     DisplayColumn(col);
  286.  
  287.     return;
  288. }
  289.  
  290.  
  291. void FromStock(int cycle, int stockmove)
  292. {
  293.     unsigned char oldpile, oldstock;
  294.     int i;
  295.  
  296.     if (stock != NOCARD) {
  297.     for (i = 0; i < stockmove && stock != NOCARD; i++) {
  298.         oldpile = pile;
  299.         pile = stock;
  300.         stock = next[stock];
  301.         next[pile] = oldpile;
  302.         cards[pile] = POSN(PILE, 0);
  303.     }
  304.  
  305.     DisplayStockPile();
  306.  
  307.     } else if ((++stockcycled) / stockmove == 0 || cycle) {
  308.     while (pile != NOCARD) {
  309.         oldstock = stock;
  310.         stock = pile;
  311.         pile = next[pile];
  312.         next[stock] = oldstock;
  313.         cards[stock] = POSN(STOCK, 0);
  314.         hidden[stock] = 0;
  315.     }
  316.  
  317.     DisplayStockPile();
  318.  
  319.     }
  320.  
  321.     return;
  322. }
  323.  
  324.  
  325. void MoveOff(unsigned char card)
  326. {
  327.     unsigned char i;
  328.     short oldcol;
  329.  
  330.     if (card == pile && TYPE(card) == foundation[SUIT(card)]) {
  331.     pile = next[card];
  332.     next[card] = NOCARD;
  333.     cards[card] = POSN(FOUNDATION, 0);
  334.     foundation[SUIT(card)]++;
  335.  
  336.     DisplayFoundations();
  337.     DisplayStockPile();
  338.     }
  339.     else if (next[card] == NOCARD && TYPE(card) == foundation[SUIT(card)]) {
  340.     oldcol = -1;
  341.     for (i = 0; oldcol == -1 && i < COLUMNS; i++) {
  342.         if (column[i] == card) {
  343.         column[i] = NOCARD;
  344.         oldcol = i;
  345.         }
  346.     }
  347.     for (i = 0; oldcol == -1 && i < NUMCARDS; i++) {
  348.         if (next[i] == card) {
  349.         if (hidden[i])
  350.             hidden[i] = 0;
  351.         next[i] = NOCARD;
  352.         oldcol = COL(cards[i]);
  353.         }
  354.     }
  355.  
  356.     cards[card] = POSN(FOUNDATION, 0);
  357.     foundation[SUIT(card)]++;
  358.  
  359.     DisplayFoundations();
  360.     DisplayColumn((short)oldcol);
  361.     }
  362.  
  363.     return;
  364. }
  365.  
  366.  
  367. short CanMoveOff(unsigned char card)
  368. {
  369.     if (foundation[SUIT(card)] != TYPE(card) || 
  370.     (COL(cards[card]) != PILE && next[card] != NOCARD))
  371.     return IMPOSSIBLE;
  372.  
  373.     if (LowestFoundation((unsigned char)SUIT(card)))
  374.     return DESIRABLE;
  375.  
  376.     return POSSIBLE;
  377. }
  378.  
  379.  
  380. unsigned char LowestFoundation(unsigned char suit)
  381. {
  382.     unsigned char i;
  383.  
  384.     for (i = 0; i < NUMSUITS; i++)
  385.     if (foundation[i] < foundation[suit])
  386.         return FALSE;
  387.     return TRUE;
  388. }
  389.